/**
 * 分类标签公用接口
 *
 * @author qiushengqi <shancci@sina.com>
 *
 * $Id$
 */

;(function(W, $, undefined) {
	var hd = W.hd || {}, UD = 'undefined';

	var ID_INDEX = 0, NAME_INDEX = 1;

	var MAX_LEVEL = 4; MIN_LEVEL = 1;

	var MAP = {}, BIN = {}, NAMES = {}, parents = {}, noop = function() {}, DATA_LOADED = false;

	var defer = $.Deferred();

	function _init() {
		var leveled, level = MAX_LEVEL, parent, clist, id, name, k, v;

		for ( ; level >= MIN_LEVEL; --level) {
			leveled = MAP[level];

			for (parent in leveled) {
				clist = leveled[parent];

				parent = parseInt(parent);

				parents[parent] = parent;

				for (k in clist) {
					v = clist[k];

					id = v[ID_INDEX];
					name = v[NAME_INDEX];

					BIN[id] = {
						'id' : id,
						'name' : name,
						'level' : level,
						'parent' : parent,
						'children' : typeof(parents[id]) !== UD
					};

					if (typeof(NAMES[name]) === UD) {
						NAMES[name] = {};
					}

					NAMES[name][id] = id;
				}
			}
		}

		DATA_LOADED = true;
		defer.resolve();
	}

	(function _loadCSS() {
		$('<link rel="stylesheet" href="/public/css/tagcate.css" type="text/css">').appendTo('body');
	})();

	var ACTIVE_CLASS = 'label-success', CHOSEN_CLASS = 'label-danger', PLAIN_CLASS = 'label-info';

	var nav_wrap = ['<ul class="cate-list">', '</ul>'];

	var ITEM_TPL = '<li data-cid="{ID}" data-key="{KEY}" class="{CLASS}"><span class="label '+ PLAIN_CLASS +'">{CHECKBOX}<span>{NAME}</span></span></li>';

	var CHECKBOX_TPL = '<input type="checkbox" value="{ID}" /> ';

	function _constructElements(level, id) {
		var leveled = MAP[level];

		if (typeof(leveled[id]) === UD) {
			return '';
		}

		var items = [], list = leveled[id], l = list.length, cate, v;

		for (var i = 0; i < l; ++i) {
			v = list[i];

			cate = BIN[v[ID_INDEX]];

			items.push(ITEM_TPL.replace('{ID}', cate.id)
				.replace('{NAME}', cate.name)
				.replace('{KEY}', cate.name)
				.replace('{CLASS}', cate.children ? 'cate-parent' : 'cate-child')
				//.replace('{CHECKBOX}', cate.children ? '' : CHECKBOX_TPL.replace('{ID}', cate.id)));
		        .replace('{CHECKBOX}', cate.children ? '+ ' + CHECKBOX_TPL.replace('{ID}', cate.id) : CHECKBOX_TPL.replace('{ID}', cate.id)));
		}

		return items;
	}

	var LEVEL_WRAPPER_TPL = '<div class="cate-level-wrapper" data-level="{LEVEL}"><h4>第{LEVEL_NAME}级分类：</h4></div>';
	var LEVEL_NAME_MAP = {1: '一', 2: '二', 3: '三', 4: '四'};

	hd.tools = hd.tools || {};

	var defs = {
		// 指定分类最外层容器的ID
		'id' : 'cate-wrapper',
		// 将分类最外层容器插入到DOM中
		'born' : function($w) {
			$w.append('body');
		},
		// 选中分类后的回调
		'onSelect' : noop,
		// 取消选中分类后的回调
		'onCancel' : noop,
		// 清除所有选中分类后的回调
		'onClear' : noop
	};

	hd.tools.tagcate = function(options) {
		var opts = $.extend({}, defs, options), dt, ot;

		for( var d in defs ) {
			dt = defs[d];
			ot = opts[d];

			// 提供的参数与某认值中的值类型不一致时, 使用默认值
			if ( typeof(ot) !== typeof(dt) ) {
				ot = dt;
			}

			opts[d] = ot;
		}

		var WRAP_ID = opts['id'], $wrapper = $('<div id="'+ WRAP_ID +'" class="cate-wrapper"></div>');

		var level_wrapper_map = {}, sub_wrapper_map = {}, CHOSEN = {};

		// 构建各级容器
		function _constructWrapper() {
			// 构建每一级分类的容器
			for (var level = MIN_LEVEL; level <= MAX_LEVEL; ++level) {
				level_wrapper_map[level] = $(LEVEL_WRAPPER_TPL.replace('{LEVEL}', level)
					.replace('{LEVEL_NAME}', LEVEL_NAME_MAP[level]))
					.hide()
					.appendTo($wrapper);
			}

			var flags = {};

			$wrapper
				.on('click', 'li.cate-parent', function() {
					var $li = $(this), $span = $li.find('.label'),
						id = $li.attr('data-cid'), cate = BIN[id], level = cate.level;

					if ($span.hasClass(ACTIVE_CLASS)) {
						return;
					}

					var sub_level = MAX_LEVEL, $subs, $item, $label;

					for ( ; sub_level > level; --sub_level) {
						level_wrapper_map[sub_level].hide().find('.' + ACTIVE_CLASS).removeClass(ACTIVE_CLASS).addClass(PLAIN_CLASS);
					}

					sub_level = level + 1;

					level_wrapper_map[sub_level].find('.cate-list').hide();

					if (typeof(sub_wrapper_map[id]) === UD) {
						var elems = _constructElements(sub_level, id);

						$subs = $(nav_wrap.join(elems.join(''))).attr('data-parent', id);

						sub_wrapper_map[id] = $subs;

						level_wrapper_map[sub_level].append($subs);
					} else {
						$subs = sub_wrapper_map[id];

						// 清除已经在其它分类下取消了的同名子类
						var $selected = $subs.find('.' + CHOSEN_CLASS), l = $selected.length, i = 0;

						for ( ; i < l; ++i) {
							$label = $selected.eq(i);
							$item = $label.closest('li');

							name = $item.attr('data-key');

							if (typeof(CHOSEN[name]) === UD) {
								$label.removeClass(CHOSEN_CLASS).find('input').prop('checked', false);
							}
						}
					}

					// 初始选中项
					var k, v;

					for (k in CHOSEN) {
						v = CHOSEN[k];

						$label = $subs.find('li[data-key="'+ v +'"] .label');

						if ($label.length && !$label.hasClass(CHOSEN_CLASS)) {
							$label.addClass(CHOSEN_CLASS).find('input').prop('checked', true);
						}
					}

					$subs.show();

					level_wrapper_map[sub_level].show();

					if (!$span.hasClass(CHOSEN_CLASS)) {
						$span.removeClass(PLAIN_CLASS).addClass(ACTIVE_CLASS);
					}

					$li.siblings('li').find('.label').removeClass(ACTIVE_CLASS).addClass(PLAIN_CLASS);
                    if (!$span.hasClass(ACTIVE_CLASS)) {
                        $span.removeClass(PLAIN_CLASS).addClass(ACTIVE_CLASS);
                    }
				})
				.on('click', 'li.cate-child', function() {
					var $li = $(this), $span = $li.find('.label');

					$li.find('input[type="checkbox"]').trigger('click');
				})
				.on('click', 'input[type="checkbox"]', function(e) {
					var $c = $(this), $span = $c.closest('.label'), $li = $c.closest('li'),
						id = $li.attr('data-cid'), key = $li.attr('data-key'), cate = BIN[id], level = cate.level;

					if ($c.prop('checked')) {
						$span.addClass(CHOSEN_CLASS);
                        // 选中父级分类
                        var $pli, pcate = {}, pcid = cate.parent;
                        while (pcid != 0) {
                            pcate = BIN[pcid];
                            $pli = $('#cate-wrapper').find('li[data-key="'+ pcate.name +'"]');
                            $pli.find('input[type="checkbox"]').prop('checked', true);
                            $pli.find('.label').addClass(CHOSEN_CLASS);
                            select(pcate.name);
                            pcid = pcate.parent;
                        }
						select(key);
					} else {
						$span.removeClass(CHOSEN_CLASS);

						cancel(key);
					}

					e.stopPropagation();
				});
		}

		function _uncheck(names) {
			var i = 0, l = names.length, name, $cate_list = $wrapper.find('.cate-list'), nlist, k, d, cate;

			for ( ; i < l; ++i) {
				name = names[i];

				nlist = NAMES[name];

				for (k in nlist) {
					d = nlist[k];

					if (typeof(BIN[d]) !== UD) {
						cate = BIN[d];

						$cate_list
							.filter('[data-parent="'+ cate.parent +'"]:visible')
							.find('li[data-key="'+ cate.name +'"] input[type="checkbox"]:checked')
							.trigger('click');
					}
				}

				// 不能依赖 trigger 来清除, 因为有可能该项还未来得及在页面中渲染
				delete CHOSEN[name];
			}
		}

		if (!DATA_LOADED) {
			$.ajax({
				url : '/public/js/tagcate.json',
				dataType : 'script',
				cache: true,
				type : 'GET',
				success : function() {
					if (typeof(_MAP) === 'object') {
						MAP = _MAP;

						_init();
					}
				}
			});
		} else {
			defer.resolve();
		}

		$.when(defer).done(function() {
			_build();
		});

		// 构建一级分类
		function _build() {
			var primary_elems = _constructElements(1, 0);

			var $primary_cate_wrapper = $(nav_wrap.join(primary_elems.join('')));

			// 渲染第一级分类并展示
			level_wrapper_map[MIN_LEVEL].append($primary_cate_wrapper).show();

			opts.born.call(self, $wrapper);
		}

		_constructWrapper();

		// 获取所有指定层级中父类parent下的所有直接下级子类
		function getByLevel(level, parent) {
			if (typeof(MAP[level]) === UD) {
				return;
			}

			var leveled = MAP[level];

			var tp = typeof(parent);
			if (tp === 'number' || tp === 'string') {
				if (typeof(leveled[tp]) === UD) {
					return;
				}

				return leveled[tp];
			}

			return leveled;
		}

		// 获取所有选中分类
		function getSelected() {
			var k, v, rets = [];

			for (k in CHOSEN) {
				if (CHOSEN.hasOwnProperty(k)) {
					v = CHOSEN[k];

					rets.push(v);
				}
			}

			return rets;
		}

		// 选择指定分类
		function select(names) {
			if (!$.isArray(names)) {
				names = [names];
			}

			var k = 0, name, l = names.length, cate, tp, added = [], nlist, v, pcid, pcate;

			for ( ; k < l; ++k) {
				name = names[k];

				if (typeof(name) !== 'string') {
					continue;
				}

				nlist = NAMES[name];

				for (k in nlist) {
					v = nlist[k];

					if (typeof(BIN[v]) !== UD) {
						cate = BIN[v];

						// 只允许选择最后一级分类
						//if (!cate.children) {
							CHOSEN[name] = name;

							added.push(name);

							break;
						//}
					}
				}
			}

			if (added.length) {
				opts.onSelect(added);
			}

			return added;
		}

		// 取消选中指定分类
		function cancel(cates) {
			if (!$.isArray(cates)) {
				cates = [cates];
			}

			var i = 0, v, l = cates.length, cate, tp, lists = [], name, nlist, k, del_flag;

			for ( ; i < l; ++i) {
				name = cates[i];

				if (typeof(name) !== 'string') {
					continue;
				}

				nlist = NAMES[name];

				for (k in nlist) {
					v = nlist[k];
					del_flag = false;

					if (typeof(BIN[v]) !== UD) {
						cate = BIN[v];

						// 只允许选择最后一级分类
						//if (!cate.children) {
							if (!del_flag) {
								delete CHOSEN[name];

								lists.push(name);

								del_flag = true;

								break;
							}
						//}
					}
				}
			}

			if (lists.length) {
				opts.onCancel(lists);
			}

			return lists;
		}

		var self = {
			getByLevel : getByLevel,
			getSelected : getSelected,
			select : function(cates) {
				if (!$.isArray(cates)) {
					cates = [cates];
				}

				var i = 0, v, l = cates.length, cate, tp, lists = [], nlist, name, k, $pli;

				for ( ; i < l; ++i) {
					name = cates[i];

					if (typeof(name) !== 'string') {
						continue;
					}

					nlist = NAMES[name];

					for (k in nlist) {
						v = nlist[k];

						if (typeof(BIN[v]) !== UD) {
							cate = BIN[v];

                            if (cate.parent === 0) {
                                $pli = $('#cate-wrapper').find('li[data-key="'+ cate.name +'"]');
                                $pli.find('input[type="checkbox"]').prop('checked', true);
                                if (!$pli.find('.label').hasClass(CHOSEN_CLASS)) {
                                    $pli.find('.label').addClass(CHOSEN_CLASS);
                                }
                            }

							// 只允许选择最后一级分类
							//if (!cate.children && typeof(CHOSEN[name]) === UD) {
							if (typeof(CHOSEN[name]) === UD) {
								CHOSEN[name] = name;

								lists.push(name);

								break;
							}
						}
					}
				}

				if (lists.length) {
					opts.onSelect.call(self, lists);
				}
			},
			cancel : function(cates) {
				if (!$.isArray(cates)) {
					cates = [cates];
				}

				var i = 0, v, l = cates.length, cate, tp, lists = [], name;

				for ( ; i < l; ++i) {
					name = cates[i];

					if (typeof(name) !== 'string') {
						continue;
					}

					if (typeof(NAMES[name]) !== UD) {
						lists.push(name);
					}
				}

				if (lists.length) {
					_uncheck(lists);
				}
			},
			clear : function() {
				var lists = [], k, name;

				for (k in CHOSEN) {
					name = CHOSEN[k];

					if (typeof(NAMES[name]) !== UD) {
						lists.push(name);
					}
				}

				if (lists.length) {
					_uncheck(lists);

					opts.onClear(lists);
				}

				self.toggle();

				return lists;
			},
			toggle : function() {
					var level = MAX_LEVEL, $subs;

					for ( ; level >= MIN_LEVEL; --level) {
						if ( typeof(level_wrapper_map[level]) !== UD ) {
							$subs = level_wrapper_map[level];

							$subs.find('.' + ACTIVE_CLASS).removeClass(ACTIVE_CLASS).addClass(PLAIN_CLASS);

							if ( level > MIN_LEVEL ) {
								$subs.hide();
							}
						}
					}
			},
			id : WRAP_ID,
			$wrapper : $wrapper
		};

		return self;
	};

	W.hd = hd;

})(window, jQuery);
